package com.runa.persistence.util;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.filter.LevelFilter;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import com.runa.monitor.comm.dto.newComm.AsynResult;
import com.runa.persistence.SerializeUtil;
import com.runa.persistence.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static ch.qos.logback.core.spi.FilterReply.ACCEPT;
import static ch.qos.logback.core.spi.FilterReply.DENY;


/**
 * 2024/10/28 11:11
 * zhangYB
 */
@Slf4j
public class LogUtil {

    //对外暴露日志对象：每次拿的对象从内存里拿，没有再构建
    private static Map<String, Logger> container = new ConcurrentHashMap<>();

    private static LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

    public static void main(String[] args) {
        getLog("80000859", "瑞纳DTU").info("ceshi");
    }

    public static void linkDetect(String taskName, String factoryName, byte[] data, int length, String mark) {
        try {
            Logger logger = getLog(taskName, factoryName);
            if (null != logger) {
                logger.info("{}: {}", mark, byteToHexString(data, 0, length));
            }
        } catch (Exception e) {
            log.error("linkDetect: {} {} {}", taskName, factoryName, e);
        }

    }

    public static void getLogAndInfo(String taskName, String folder, String format, Object... arguments) {
        try {
            Logger logger = getLog(taskName, folder);
            if (null != logger) {
                logger.info(format, arguments);
            }
        } catch (Exception e) {
            log.error("info: {} {} {} {} {} ", taskName, folder, format, arguments, e);
        }
    }

    public static void info(String taskName, String format, Object... arguments) {
        try {
            Logger logger = getLogger(taskName);
            if (null != logger) {
                logger.info(format, arguments);
            }
        } catch (Exception e) {
            log.error("info: {} {} {} {} ", taskName, format, arguments, e);
        }
    }

    public static void info(String taskName, byte[] data, String format, Object... arguments) {
        info(taskName, data, data.length, format, arguments);
    }

    public static void info(String taskName, byte[] data, int length, String format, Object... arguments) {
        format = String.format(format.replaceAll("\\{}", "%s"), arguments);
        info(taskName, "{}: {}", format, byteToHexString(data, 0, length));
    }

    public static Logger getLog(String taskName, String folder) {
        if (StringUtil.isBlank(taskName) || StringUtil.isBlank(folder)) {
            return null;
        }
        Logger logger = getLogger(taskName);
        if (null == logger) {
            synchronized (container) {
                logger = getLogger(taskName);
                if (null == logger) {
                    logger = createLogger(taskName, "message/" + folder + "/" + taskName + "/");
                }
            }
        }
        return logger;
    }


//    public static Logger getLog(String taskName) {
//        Logger logger = getLogger(taskName);
//        if (null == logger) {
//            createLogger(taskName, "message/" + taskName);
//            logger = getLogger(taskName);
//        }
//        return logger;
//    }

    //系统初始化后，可以创建一次对应执行任务的log
    public static Logger createLogger(String taskName, String logPath) {
        if (StringUtil.isNotBlank(taskName)) {
            Logger logger = build(taskName, logPath);
            container.put(taskName, logger);
            return logger;
        }
        return null;
    }

    public static Logger getLogger(String taskName) {
        if (StringUtil.isBlank(taskName)) {
            return null;
        }
        Logger logger = container.get(taskName);
        return logger;
    }

    //构建Logger对象，给Logger指定appender，该方法不对外暴露
    private static Logger build(String taskName, String logPath) {
        RollingFileAppender appender = getAppender(logPath, taskName);
        Logger logger = context.getLogger(taskName);
        logger.addAppender(appender);
        logger.setAdditive(false);
        return logger;
    }

    /**
     * 通过传入的任务名字,动态设置appender
     *
     * @param taskName
     * @return
     */
    private static RollingFileAppender getAppender(String logPath, String taskName) {
        RollingFileAppender appender = new RollingFileAppender();
        //appender的name属性
        appender.setName(taskName);
        appender.setContext(context);
        String absolutePath = new File(logPath, taskName + ".log").getAbsolutePath();
        appender.setFile(absolutePath);

        //设置日志文件输出格式
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(context);
        encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{16} - %msg%n");
        encoder.setCharset(StandardCharsets.UTF_8);
        encoder.start();

        //设置日志记录器的滚动策略（如果要限制文件的大小请使用-----SizeAndTimeBasedRollingPolicy）
        TimeBasedRollingPolicy policy = new TimeBasedRollingPolicy();
        policy.setFileNamePattern(logPath + taskName + ".%d{yyyy-MM-dd}.zip");
        policy.setMaxHistory(180);
        policy.setParent(appender); //设置父节点是appender
        policy.setContext(context);
        policy.start();

        LevelFilter levelFilter = getLevelFilter(Level.INFO);
        levelFilter.start();

        //加入下面两个节点
        appender.setRollingPolicy(policy);
        appender.setEncoder(encoder);
        appender.addFilter(levelFilter);
        appender.start();
        return appender;
    }


    public static LevelFilter getLevelFilter(Level level){
        LevelFilter levelFilter = new LevelFilter();
        levelFilter.setLevel(level);
        levelFilter.setOnMatch(ACCEPT);
        levelFilter.setOnMismatch(DENY);
        return levelFilter;
    }

    public static String byteToHexString(byte[] b) {
        if (null == b) {
            return null;
        }
        return byteToHexString(b, 0, b.length);
    }

    public static String byteToHexString(byte[] b, int offset, int length){
        if (length > b.length) {
            length = b.length;
        }
        StringBuilder sb = new StringBuilder();
        String tmp;
        int end = offset+length;
        if(offset>=0 && length>0 && end<=b.length) {
            for (int index=offset; index<end; index++) {
                tmp = Integer.toHexString(0xFF & b[index]);
                if (tmp.length() == 1) {
                    tmp = "0" + tmp;
                }
                sb.append(tmp);
            }
        }
        return sb.toString().toUpperCase();
    }

    public static void onofflineChange(byte[] payload) {
        try {
            getLogAndInfo("onoffline", "上下线状态", new String(payload));
        } catch (Exception e) {
            log.error("statusChange: {}", e);
        }
    }

}
